using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 环境扫描器
    /// 负责扫描Unity环境并提取原始事件信息
    /// </summary>
    public class EnvironmentScanner : MonoBehaviour
    {
        [Header("扫描配置")]
        [SerializeField] private LayerMask agentLayers = 1 << 8; // 假设智能体在第8层
        [SerializeField] private LayerMask objectLayers = 1 << 9; // 假设对象在第9层
        [SerializeField] private LayerMask tileLayers = 1 << 10; // 假设瓦片在第10层
        [SerializeField] private float movementThreshold = 0.1f; // 移动阈值
        [SerializeField] private bool enableScanLogging = false;
        
        // 缓存数据
        private Dictionary<string, Vector3> lastKnownPositions;
        private Dictionary<string, AgentState> lastKnownStates;
        private Dictionary<string, DateTime> lastUpdateTimes;
        
        private void Awake()
        {
            InitializeScanner();
        }
        
        private void InitializeScanner()
        {
            lastKnownPositions = new Dictionary<string, Vector3>();
            lastKnownStates = new Dictionary<string, AgentState>();
            lastUpdateTimes = new Dictionary<string, DateTime>();
        }
        
        /// <summary>
        /// 扫描环境获取感知对象
        /// </summary>
        public List<PerceivedObject> ScanEnvironment(Vector3 center, float radius, LayerMask layers)
        {
            var perceivedObjects = new List<PerceivedObject>();
            
            try
            {
                // 使用OverlapSphere获取范围内的所有碰撞器
                var colliders = Physics.OverlapSphere(center, radius, layers);
                
                if (enableScanLogging)
                {
                    Debug.Log($"[EnvironmentScanner] Found {colliders.Length} colliders in range");
                }
                
                foreach (var collider in colliders)
                {
                    var perceivedObject = CreatePerceivedObject(collider);
                    if (perceivedObject != null)
                    {
                        perceivedObjects.Add(perceivedObject);
                    }
                }
                
                // 按距离排序
                perceivedObjects = perceivedObjects
                    .OrderBy(obj => Vector3.Distance(center, obj.position))
                    .ToList();
            }
            catch (Exception ex)
            {
                Debug.LogError($"[EnvironmentScanner] Error scanning environment: {ex.Message}");
            }
            
            return perceivedObjects;
        }
        
        /// <summary>
        /// 从感知对象提取原始事件
        /// </summary>
        public List<RawEvent> ExtractRawEvents(List<PerceivedObject> perceivedObjects)
        {
            var rawEvents = new List<RawEvent>();
            
            try
            {
                foreach (var obj in perceivedObjects)
                {
                    // 提取移动事件
                    var movementEvents = ExtractMovementEvents(obj);
                    rawEvents.AddRange(movementEvents);
                    
                    // 提取交互事件
                    var interactionEvents = ExtractInteractionEvents(obj);
                    rawEvents.AddRange(interactionEvents);
                    
                    // 提取对话事件
                    var conversationEvents = ExtractConversationEvents(obj);
                    rawEvents.AddRange(conversationEvents);
                    
                    // 提取状态变化事件
                    var stateEvents = ExtractStateChangeEvents(obj);
                    rawEvents.AddRange(stateEvents);
                }
                
                // 更新缓存
                UpdateCache(perceivedObjects);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[EnvironmentScanner] Error extracting events: {ex.Message}");
            }
            
            return rawEvents;
        }
        
        /// <summary>
        /// 创建感知对象
        /// </summary>
        private PerceivedObject CreatePerceivedObject(Collider collider)
        {
            try
            {
                var perceivedObject = new PerceivedObject
                {
                    id = GetObjectId(collider),
                    name = collider.name,
                    position = collider.transform.position,
                    rotation = collider.transform.rotation,
                    bounds = collider.bounds,
                    layer = collider.gameObject.layer,
                    timestamp = DateTime.Now
                };
                
                // 确定对象类型
                perceivedObject.objectType = DetermineObjectType(collider);
                
                // 获取额外信息
                ExtractAdditionalInfo(collider, perceivedObject);
                
                return perceivedObject;
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"[EnvironmentScanner] Failed to create perceived object for {collider.name}: {ex.Message}");
                return null;
            }
        }
        
        /// <summary>
        /// 获取对象ID
        /// </summary>
        private string GetObjectId(Collider collider)
        {
            // 优先使用自定义ID组件
            var idComponent = collider.GetComponent<UniqueId>();
            if (idComponent != null)
            {
                return idComponent.Id;
            }
            
            // 使用实例ID作为后备
            return $"{collider.name}_{collider.GetInstanceID()}";
        }
        
        /// <summary>
        /// 确定对象类型
        /// </summary>
        private PerceivedObjectType DetermineObjectType(Collider collider)
        {
            // 检查是否有智能体组件
            if (collider.GetComponent<AgentController>() != null)
            {
                return PerceivedObjectType.Agent;
            }
            
            // 检查是否有瓦片组件
            if (collider.GetComponent<Tile>() != null)
            {
                return PerceivedObjectType.Tile;
            }
            
            // 检查是否有交互组件
            if (collider.GetComponent<InteractableObject>() != null)
            {
                return PerceivedObjectType.InteractableObject;
            }
            
            // 基于层判断
            if (IsInLayerMask(collider.gameObject.layer, agentLayers))
            {
                return PerceivedObjectType.Agent;
            }
            else if (IsInLayerMask(collider.gameObject.layer, tileLayers))
            {
                return PerceivedObjectType.Tile;
            }
            else if (IsInLayerMask(collider.gameObject.layer, objectLayers))
            {
                return PerceivedObjectType.InteractableObject;
            }
            
            return PerceivedObjectType.StaticObject;
        }
        
        /// <summary>
        /// 提取额外信息
        /// </summary>
        private void ExtractAdditionalInfo(Collider collider, PerceivedObject perceivedObject)
        {
            // 智能体信息
            var agent = collider.GetComponent<AgentController>();
            if (agent != null)
            {
                perceivedObject.properties["agentName"] = agent.AgentName;
                perceivedObject.properties["currentAction"] = agent.GetCurrentAction();
                perceivedObject.properties["isMoving"] = agent.IsMoving();
                perceivedObject.properties["isInConversation"] = agent.IsInConversation();
                
                if (agent.IsInConversation())
                {
                    perceivedObject.properties["conversationPartner"] = agent.GetConversationPartner();
                    perceivedObject.properties["conversationId"] = agent.GetConversationId();
                }
            }
            
            // 瓦片信息
            var tile = collider.GetComponent<Tile>();
            if (tile != null)
            {
                perceivedObject.properties["tileType"] = tile.TileType.ToString();
                perceivedObject.properties["objects"] = tile.GetObjectsOnTile();
                perceivedObject.properties["agents"] = tile.GetAgentsOnTile();
            }
            
            // 交互对象信息
            var interactable = collider.GetComponent<InteractableObject>();
            if (interactable != null)
            {
                perceivedObject.properties["isInteractable"] = interactable.IsInteractable();
                perceivedObject.properties["interactionType"] = interactable.GetInteractionType();
                perceivedObject.properties["isInUse"] = interactable.IsInUse();
            }
        }
        
        /// <summary>
        /// 提取移动事件
        /// </summary>
        private List<RawEvent> ExtractMovementEvents(PerceivedObject obj)
        {
            var events = new List<RawEvent>();
            
            if (obj.objectType != PerceivedObjectType.Agent)
                return events;
            
            // 检查是否有位置变化
            if (lastKnownPositions.TryGetValue(obj.id, out var lastPosition))
            {
                var distance = Vector3.Distance(lastPosition, obj.position);
                if (distance > movementThreshold)
                {
                    var moveEvent = new RawEvent
                    {
                        id = $"move_{obj.id}_{DateTime.Now.Ticks}",
                        type = EventType.Movement,
                        subject = obj.name,
                        predicate = "moved from",
                        objectEntity = $"{lastPosition} to {obj.position}",
                        location = obj.position,
                        timestamp = DateTime.Now
                    };
                    
                    moveEvent.metadata["previousPosition"] = lastPosition;
                    moveEvent.metadata["currentPosition"] = obj.position;
                    moveEvent.metadata["distance"] = distance;
                    
                    events.Add(moveEvent);
                }
            }
            
            return events;
        }
        
        /// <summary>
        /// 提取交互事件
        /// </summary>
        private List<RawEvent> ExtractInteractionEvents(PerceivedObject obj)
        {
            var events = new List<RawEvent>();
            
            if (obj.objectType == PerceivedObjectType.InteractableObject)
            {
                if (obj.properties.ContainsKey("isInUse") && (bool)obj.properties["isInUse"])
                {
                    var interactionEvent = new RawEvent
                    {
                        id = $"interact_{obj.id}_{DateTime.Now.Ticks}",
                        type = EventType.Interaction,
                        subject = "someone", // 需要进一步确定使用者
                        predicate = "is using",
                        objectEntity = obj.name,
                        location = obj.position,
                        timestamp = DateTime.Now
                    };
                    
                    if (obj.properties.ContainsKey("interactionType"))
                    {
                        interactionEvent.metadata["interactionType"] = obj.properties["interactionType"];
                    }
                    
                    events.Add(interactionEvent);
                }
            }
            
            return events;
        }
        
        /// <summary>
        /// 提取对话事件
        /// </summary>
        private List<RawEvent> ExtractConversationEvents(PerceivedObject obj)
        {
            var events = new List<RawEvent>();
            
            if (obj.objectType == PerceivedObjectType.Agent && 
                obj.properties.ContainsKey("isInConversation") && 
                (bool)obj.properties["isInConversation"])
            {
                var conversationEvent = new RawEvent
                {
                    id = $"conversation_{obj.properties["conversationId"]}_{DateTime.Now.Ticks}",
                    type = EventType.Conversation,
                    subject = obj.name,
                    predicate = "is talking with",
                    objectEntity = obj.properties["conversationPartner"].ToString(),
                    location = obj.position,
                    timestamp = DateTime.Now
                };
                
                conversationEvent.metadata["conversationId"] = obj.properties["conversationId"];
                conversationEvent.metadata["participants"] = new List<string> 
                { 
                    obj.name, 
                    obj.properties["conversationPartner"].ToString() 
                };
                
                events.Add(conversationEvent);
            }
            
            return events;
        }
        
        /// <summary>
        /// 提取状态变化事件
        /// </summary>
        private List<RawEvent> ExtractStateChangeEvents(PerceivedObject obj)
        {
            var events = new List<RawEvent>();
            
            if (obj.objectType == PerceivedObjectType.Agent)
            {
                // 检查动作变化
                if (obj.properties.ContainsKey("currentAction"))
                {
                    var currentAction = obj.properties["currentAction"].ToString();
                    
                    if (lastKnownStates.TryGetValue(obj.id, out var lastState))
                    {
                        if (lastState.currentAction != currentAction)
                        {
                            var actionEvent = new RawEvent
                            {
                                id = $"action_{obj.id}_{DateTime.Now.Ticks}",
                                type = EventType.Action,
                                subject = obj.name,
                                predicate = "started",
                                objectEntity = currentAction,
                                location = obj.position,
                                timestamp = DateTime.Now
                            };
                            
                            actionEvent.metadata["previousAction"] = lastState.currentAction;
                            actionEvent.metadata["currentAction"] = currentAction;
                            
                            events.Add(actionEvent);
                        }
                    }
                }
            }
            
            return events;
        }
        
        /// <summary>
        /// 更新缓存
        /// </summary>
        private void UpdateCache(List<PerceivedObject> objects)
        {
            foreach (var obj in objects)
            {
                lastKnownPositions[obj.id] = obj.position;
                lastUpdateTimes[obj.id] = DateTime.Now;
                
                if (obj.objectType == PerceivedObjectType.Agent && obj.properties.ContainsKey("currentAction"))
                {
                    var state = new AgentState
                    {
                        currentAction = obj.properties["currentAction"].ToString(),
                        currentLocation = obj.position,
                        isInConversation = obj.properties.ContainsKey("isInConversation") && (bool)obj.properties["isInConversation"]
                    };
                    
                    if (state.isInConversation && obj.properties.ContainsKey("conversationPartner"))
                    {
                        state.conversationPartner = obj.properties["conversationPartner"].ToString();
                    }
                    
                    lastKnownStates[obj.id] = state;
                }
            }
        }
        
        /// <summary>
        /// 检查层是否在LayerMask中
        /// </summary>
        private bool IsInLayerMask(int layer, LayerMask layerMask)
        {
            return (layerMask.value & (1 << layer)) != 0;
        }
        
        /// <summary>
        /// 清理过期缓存
        /// </summary>
        public void CleanupCache(TimeSpan maxAge)
        {
            var cutoffTime = DateTime.Now - maxAge;
            var expiredKeys = lastUpdateTimes
                .Where(kv => kv.Value < cutoffTime)
                .Select(kv => kv.Key)
                .ToList();
            
            foreach (var key in expiredKeys)
            {
                lastKnownPositions.Remove(key);
                lastKnownStates.Remove(key);
                lastUpdateTimes.Remove(key);
            }
        }
        
        /// <summary>
        /// 获取扫描统计信息
        /// </summary>
        public string GetScanStats()
        {
            return $"Cached Positions: {lastKnownPositions.Count}, Cached States: {lastKnownStates.Count}";
        }
    }
    
    /// <summary>
    /// 感知对象数据结构
    /// </summary>
    [System.Serializable]
    public class PerceivedObject
    {
        public string id;
        public string name;
        public Vector3 position;
        public Quaternion rotation;
        public Bounds bounds;
        public int layer;
        public PerceivedObjectType objectType;
        public DateTime timestamp;
        public Dictionary<string, object> properties;
        
        public PerceivedObject()
        {
            properties = new Dictionary<string, object>();
            timestamp = DateTime.Now;
        }
    }
    
    /// <summary>
    /// 感知对象类型
    /// </summary>
    public enum PerceivedObjectType
    {
        Agent,              // 智能体
        Tile,               // 瓦片
        InteractableObject, // 可交互对象
        StaticObject,       // 静态对象
        Environment         // 环境对象
    }
}